package org.apache.commons.ognl;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* Generated By:JavaCC: Do not edit this line. JJTOgnlParserState.java Version 4.1d1 */

import java.util.ArrayList;
import java.util.List;

/**
 */
public class JJTOgnlParserState
{
    private final List<Node> nodes;

    private final List<Integer> marks;

    private int numNodesOnStack;

    private int currentMark;

    private boolean nodeCreated;

    public JJTOgnlParserState()
    {
        nodes = new ArrayList<Node>();
        marks = new ArrayList<Integer>();
        numNodesOnStack = 0;
        currentMark = 0;
    }

    /*
     * Determines whether the current node was actually closed and pushed. This should only be called in the final user
     * action of a node scope.
     */
    public boolean nodeCreated()
    {
        return nodeCreated;
    }

    /*
     * Call this to reinitialize the node stack. It is called automatically by the parser's ReInit() method.
     */
    public void reset()
    {
        nodes.clear();
        marks.clear();
        numNodesOnStack = 0;
        currentMark = 0;
    }

    /*
     * Returns the root node of the AST. It only makes sense to call this after a successful parse.
     */
    public Node rootNode()
    {
        return nodes.get( 0 );
    }

    /* Pushes a node on to the stack. */
    public void pushNode( Node node )
    {
        nodes.add( node );
        ++numNodesOnStack;
    }

    /*
     * Returns the node on the top of the stack, and remove it from the stack.
     */
    public Node popNode()
    {
        if ( --numNodesOnStack < currentMark )
        {
            currentMark = marks.remove( marks.size() - 1 );
        }
        return nodes.remove( nodes.size() - 1 );
    }

    /* Returns the node currently on the top of the stack. */
    public Node peekNode()
    {
        return nodes.get( nodes.size() - 1 );
    }

    /*
     * Returns the number of children on the stack in the current node scope.
     */
    public int nodeArity()
    {
        return numNodesOnStack - currentMark;
    }

    public void clearNodeScope( Node unused )
    {
        while ( numNodesOnStack > currentMark )
        {
            popNode();
        }
        currentMark = marks.remove( marks.size() - 1 );
    }

    public void openNodeScope( Node node )
    {
        marks.add( currentMark );
        currentMark = numNodesOnStack;
        node.jjtOpen();
    }

    /*
     * A definite node is constructed from a specified number of children. That number of nodes are popped from the
     * stack and made the children of the definite node. Then the definite node is pushed on to the stack.
     */
    public void closeNodeScope( Node node, int num )
    {
        currentMark = marks.remove( marks.size() - 1 );
        while ( num-- > 0 )
        {
            Node poppedNode = popNode();
            poppedNode.jjtSetParent( node );
            node.jjtAddChild( poppedNode, num );
        }
        node.jjtClose();
        pushNode( node );
        nodeCreated = true;
    }

    /*
     * A conditional node is constructed if its condition is true. All the nodes that have been pushed since the node
     * was opened are made children of the conditional node, which is then pushed on to the stack. If the condition is
     * false the node is not constructed and they are left on the stack.
     */
    public void closeNodeScope( Node node, boolean condition )
    {
        if ( condition )
        {
            int arity = nodeArity();
            currentMark = marks.remove( marks.size() - 1 );
            while ( arity-- > 0 )
            {
                Node poppedNode = popNode();
                poppedNode.jjtSetParent( node );
                node.jjtAddChild( poppedNode, arity );
            }
            node.jjtClose();
            pushNode( node );
            nodeCreated = true;
        }
        else
        {
            currentMark = marks.remove( marks.size() - 1 );
            nodeCreated = false;
        }
    }
}
/* JavaCC - OriginalChecksum=61071c68a05e7c9104307c34a2e37165 (do not edit this line) */
